package demo.json.jackson;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import demo.vo.TimeDemoVO;
import demo.vo.common.ApiResult;
import demo.vo.json.Student;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * *
 * <li>@JsonIgnoreProperties此注解是类注解，作用是json序列化时将java bean中的一些属性忽略掉，序列化和反序列化都受影响。
 * <li>@JsonIgnore此注解用于属性或者方法上（最好是属性上），作用和上面的@JsonIgnoreProperties一样。
 * <li>@JsonFormat此注解用于属性或者方法上（最好是属性上），可以方便的把Date类型直接转化为我们想要的模式，比如@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")
 * <li>@JsonSerialize此注解用于属性或者getter方法上，用于在序列化时嵌入我们自定义的代码，比如序列化一个double时在其后面限制两位小数点。
 * <li>@JsonDeserialize此注解用于属性或者setter方法上，用于在反序列化时可以嵌入我们自定义的代码，类似于上面的@JsonSerialize
 */
public class JacksonDemo {

    private static final Logger logger = LoggerFactory.getLogger(JacksonDemo.class);

    private static final ObjectMapper objectMapper = new ObjectMapper();

    static {
        objectMapper.registerModule(new JavaTimeModule());
        // 反序列化的时候如果多了其他属性,不抛出异常
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }


    @Test
    public void testObjectMapper() throws JsonProcessingException {

        Map<String, String> params = new HashMap<>();
        params.put("username", "国米");
        params.put("password", "123456");
        String value = objectMapper.writeValueAsString(params);
        System.out.println(value);


        Student s = new Student();
        s.setCreateAt(new Date());
        s.setStudentName("Stan");
        s.setUpdateAt(new Date());
        String json = objectMapper.writeValueAsString(s);
        System.out.println(json);
        // 将JSON字符串转换为Java对象
        Student person = objectMapper.readValue(json, Student.class);
        System.out.println(person.getStudentName()); // 输出"John"
    }

    @Test
    public void testJavaObject() throws JsonProcessingException {
        ApiResult<String> result = new ApiResult<>("hello jackson");
        String str = objectMapper.writeValueAsString(result);
        System.out.println(str);

        ApiResult result2 = objectMapper.readValue(str, ApiResult.class);
        System.out.println(result2.getData());

        ApiResult<String> result3 = objectMapper.readValue(str, new TypeReference<ApiResult<String>>() {
        });
        System.out.println(result3.getData());
        result3.setData("hello world");

        List<ApiResult<String>> list = Arrays.asList(result, result3);
        String listStr = objectMapper.writeValueAsString(list);
        System.out.println(listStr);

        List<ApiResult<String>> list2 = objectMapper.readValue(listStr, new TypeReference<List<ApiResult<String>>>() {
        });
        list2.forEach(e -> System.out.println(e.getData()));

        List<ApiResult<String>> list3 = objectMapper.readValue(listStr, objectMapper.getTypeFactory().constructCollectionType(List.class, ApiResult.class));
        list2.forEach(e -> System.out.println(e.getData()));
    }

    @Test
    public void testLocalDateTime() throws JsonProcessingException {
        TimeDemoVO vo = new TimeDemoVO();
        String jsonStr = objectMapper.writeValueAsString(vo);
        System.out.println(jsonStr);
    }

    /**
     * 序列换成json时,将所有的long变成string 因为js中得数字类型不能包含所有的java long值
     */
    @Test
    public void test1() {
        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        // 反序列化的时候如果多了其他属性,不抛出异常
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.registerModule(simpleModule);
        com.fasterxml.jackson.databind.ObjectMapper bb = null;

    }

}
